import java.util.List;
import java.util.Vector;

import processing.core.PApplet;
import processing.core.PVector;

public class CopyOfMC_SoftBody extends PApplet {

	enum State {
		DRAWING,
		BORNING,
		LIVING
	}
	
	private static final long serialVersionUID = 1L;
	/**
	 * Soft Body 
	 * by Ira Greenberg.  
	 * 
	 * Softbody dynamics simulation using curveVertex() and curveTightness().
	 */

	Vector<PVector> pointsBeingDrawn;
	Vector<PVector> pointsToDraw;
	State status;
	
	// center point
	float centerX = 0; 
	float centerY = 0;
	
	float radius = 45;
	float rotAngle = -90;
	float accelX = 0; 
	float accelY = 0;
	float springing = 0.0009f; 
	float damping = 0.98f;

	//corner nodes
	int nodes = 4;
	float nodeStartX[] = new float[nodes];
	float nodeStartY[] = new float[nodes];
	float nodeX[] = new float[nodes];
	float nodeY[] = new float[nodes];
	float angle[] = new float[nodes];
	float frequency[] = new float[nodes];
	
	Vector<PVector> nodeStart = new Vector<PVector>();
	Vector<PVector> node = new Vector<PVector>();
	Vector<Float> angles = new Vector<Float>();
	Vector<Float> frequencies = new Vector<Float>();

	// soft-body dynamics
	float organicConstant = 1;

	boolean firstTime = true;
	float num1[] = new float[nodes];
	float num2[] = new float[nodes];

	public void setup() {
		status = State.DRAWING;
		size(640, 360);
		//center shape in window
		centerX = width/2;
		centerY = height/2;
		// iniitalize frequencies for corner nodes
		noStroke();
		//smooth();
		frameRate(30);
		pointsBeingDrawn = new Vector<PVector>();
		pointsToDraw = new Vector<PVector>();
	}

	public void draw() {
		background(0);
		switch (status) {
		case DRAWING:
			for (PVector point : pointsToDraw) {
				stroke(255);
				point(point.x, point.y);
			}
			
			break;
		case BORNING:
			drawShape();
			break;
		case LIVING:
			
			break;

		default:
			break;
		}
		moveShape();
	}

	public void drawShape() {
		if(firstTime) {
			for (int i = 0; i < nodes; i++) {
				frequency[i] = random(5, 12);
			}

			for(int i = 0; i < nodes; i++){
				num1[i] = random(100);
				num2[i] = random(100);
			}

			firstTime = false;
		} else {
			for (int i = 0; i < nodes; i++) {
				nodeStartX[i] = centerX + cos(radians(rotAngle)) * radius;
				nodeStartY[i] = centerY + sin(radians(rotAngle)) * radius;
				rotAngle = rotAngle + 360.0f/nodes;
			}
			// draw polygon
			curveTightness(organicConstant);
			fill(255);
			beginShape();
			for (int i = 0; i < nodes; i++) {
				curveVertex(nodeX[i], nodeY[i]);
			}
			for (int i = 0; i < nodes-1; i++) {
				curveVertex(nodeX[i], nodeY[i]);
			}
			endShape(CLOSE);
		}
	}

	public void moveShape() {
		//move center point
		float deltaX = mouseX-centerX;
		float deltaY = mouseY-centerY;

		// create springing effect
		deltaX = deltaX * springing;
		deltaY = deltaY * springing;
		accelX = accelX + deltaX;
		accelY = accelY + deltaY;

		// move predator's center
		centerX = centerX + accelX;
		centerY = centerY + accelY;

		// slow down springing
		accelX = accelX * damping;
		accelY = accelY * damping;

		// change curve tightness
		organicConstant = 1 - ((abs(accelX)+abs(accelY))*.1f);

		//move nodes
		for (int i = 0; i < nodes; i++) {
			nodeX[i] = nodeStartX[i] + sin(radians(angle[i])) * (accelX*2);
			nodeY[i] = nodeStartY[i] + sin(radians(angle[i])) * (accelY*2);
			angle[i] = angle[i] + frequency[i];
		}
	}
	
	public boolean contem(PVector current){
		boolean contem = false;
		for (PVector point : pointsBeingDrawn) {
			float cX = current.x;
			float cY = current.y;
			float pX = point.x;
			float pY = point.y;
			if(cX == pX && cY == pY){
				contem = true;
			}
		}
		return contem;
	}

	@Override
	public void mouseDragged() {
		PVector current = new PVector(mouseX, mouseY);
		if(!contem(current)){
			pointsBeingDrawn.add(current);
		} else {
			System.out.println("Ok");
			pointsToDraw = pointsBeingDrawn;
			pointsBeingDrawn.clear();
		}
	}

	static public void main(String args[]) {
		PApplet.main(new String[] { "--bgcolor=#FFFFFF", "CopyOfMC_SoftBody" });
	}
}
